﻿/*
 * MessageSerializerFactory
 * 
 * Author: snowdreamist
 * Date: 2011/12/3
 * 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BitTorrentSharp.KRPC.Messages
{
    public interface IMessageSerializerFactory
    {
        IMessageSerializer Create(Type serializerType);
    }

    public abstract class MessageSerializerFactory : IMessageSerializerFactory
    {
        private readonly object _syncRoot = new object();

        private readonly Dictionary<Type, IMessageSerializer> _serializers;
        /// <summary>
        /// Create a serializer
        /// </summary>
        /// <param name="serializerType"></param>
        /// <returns></returns>
        public IMessageSerializer Create(Type serializerType)
        {
            if (serializerType == null)
                throw new ArgumentNullException("serializerType");
            if (!serializerType.IsSubclassOf(typeof(IMessageSerializer)))
                throw new ArgumentException("Type mismatch");

            lock (this._syncRoot)
            {
                if (this._serializers.ContainsKey(serializerType))
                {
                    return this._serializers[serializerType];
                }
                else
                {
                    var serializer = this.InternalCreate(serializerType);
                    this._serializers[serializerType] = serializer;
                    return serializer;
                }
            }
        }

        protected abstract IMessageSerializer InternalCreate(Type serializerType);
    }

    public class DefaultMessageSerializerFactory : MessageSerializerFactory
    {
        protected override IMessageSerializer InternalCreate(Type serializerType)
        {
            var serializer = Activator.CreateInstance(serializerType) as IMessageSerializer;

            if (serializer == null)
                throw new ArgumentException("Type mismatch");

            return serializer;
        }
    }
}
